<template>
  <base-container>
    <!-- 搜索栏 -->
    <avue-table-search
      :option="searchOption"
      v-model="searchParams"
      @search-change="loadTableSearch"
      @search-reset="loadTableSearchReset"
    />

    <base-table-card>
      <!-- 顶部：一级类目 Tabs（由接口返回，**不添加总 Tab**） -->
      <template #header-left>
        <div class="header-left-wrap">
          <el-tabs v-model="activeLevel1Id" class="x-tabs" :stretch="false" @tab-change="handleLevel1Change">
            <el-tab-pane
              v-for="t in level1Tabs"
              :key="t.id"
              :name="String(t.id)"
              :label="`${t.categoryName}(${t.num})`"
            />
          </el-tabs>
        </div>
      </template>

      <template #header-right>
        <el-button type="primary" @click="openAddDialog">新增内容</el-button>
      </template>

      <!-- 表格 -->
      <avue-crud
        ref="crudRef"
        :option="tableOption"
        :data="tableData"
        v-model="formData"
        :page="page"
        :table-loading="tableLoading"
        @refresh-change="loadGetTableData"
        @current-change="loadTablePageChange"
        @size-change="loadTablePageSizeChange"
        @row-save="loadAdd"
        @row-update="loadEdit"
      >
        <template #categoryName="{ row }">
          {{ row.categoryName && row.categoryName.trim() ? row.categoryName : "/" }}
        </template>
        <template #displayStatus="{ row }">
          <el-switch
            v-if="row.sendStatus == '01'"
            :model-value="row.displayStatus"
            :loading="row.statusLoading"
            :active-value="1"
            :inactive-value="0"
            :disabled="!canToggleDisplay"
            :before-change="() => handleStatusChange(row)"
          />
          <span v-else>/</span>
        </template>

        <template #menu="{ row }">
          <el-button type="primary" text v-auth="[PERMS.SERVICE.CONTENT.UPDATE]" @click="openEditDialog(row)"
            >编辑</el-button
          >
          <el-button
            v-if="canSend(row)"
            v-auth="[PERMS.SERVICE.CONTENT.SEND]"
            type="primary"
            text
            :loading="row._sendLoading"
            @click="onSend(row)"
          >
            发送
          </el-button>
          <el-button type="info" v-auth="[PERMS.SERVICE.CONTENT.DELETE]" text @click="loadDel(row)">删除</el-button>
        </template>
      </avue-crud>
    </base-table-card>
  </base-container>
</template>

<script setup>
  import Option from "@/crudOption/service/list";
  import { SEND_STATUS } from "@/utils/const";
  import { ElMessageBox } from "element-plus";
  import { router } from "@/router/index";
  import { useUserInfoStore } from "@/store/modules/userInfo.js";
  import { PERMS } from "@/constants/perms.js";
  const { searchOption, tableOption } = Option();
  //pinia 隐藏/展示
  const user = useUserInfoStore();
  const canToggleDisplay = computed(() => user.hasAuth([PERMS.SERVICE.CONTENT.ENABLE]));
  tableOption.value.menu = computed(() =>
    user.hasAuth([PERMS.SERVICE.CONTENT.UPDATE, PERMS.SERVICE.CONTENT.SEND, PERMS.SERVICE.CONTENT.DELETE])
  );

  /** 是否可“立即发送” */
  const canSend = row => {
    const s = String(row.sendStatus || "");
    // 规则：未发送 / 发送失败 才能点击“发送”
    return (s === SEND_STATUS.UNSENT && row.sendMethod == "02") || s === SEND_STATUS.FAIL;
  };
  // 菜单状态展示/隐藏切换
  async function handleStatusChange(row) {
    const nextVal = row.displayStatus === 1 ? 0 : 1;
    const msg =
      nextVal === 0
        ? "确定要隐藏该内容吗？隐藏后将不被展示用户不能查看。"
        : "确定要展示该内容吗？展示后将被展示用户能查看。";
    try {
      await ElMessageBox.confirm(msg, "提示", { type: "warning" });
      row._statusLoading = true;
      await Api.service.StatusContentEnableChange({ id: row.id, displayStatus: nextVal });
      loadGetTableData();
      $msg.success(nextVal ? "已展示" : "已隐藏");
    } catch (e) {
      // 取消/失败，不变
    } finally {
      row._statusLoading = false;
    }
  }
  /** 立即发送 */
  async function onSend(row) {
    try {
      await ElMessageBox.confirm("确认要立即发送该内容吗？", "提示", { type: "warning" });
      row._sendLoading = true;
      await Api.service.ContentManualSend({ id: row.id });
      $msg.success("已提交发送");
      await loadGetTableData();
    } catch (e) {
      console.error("onSend error:", e);
      // 用户取消或接口异常都静默即可
    } finally {
      row._sendLoading = false;
    }
  }

  /* ============== 顶部 Tabs（一级类目，纯接口） ============== */
  const level1Tabs = ref([]); // [{id, categoryName, num}]
  const activeLevel1Id = ref(""); // 当前激活；初始化为列表第一个的 id

  // 统一一下 rows 字段，并兜底 num
  function normalize(rows) {
    return (rows || []).map(r => ({
      id: r.id,
      categoryName: r.categoryName ?? r.name ?? "",
      num: Number(r.num ?? r.contentNum ?? 0),
    }));
  }

  async function loadLevel1() {
    try {
      const res = await Api.service.GetLevel1CategoryList();
      const payload = res?.data ?? res;
      const rows = Array.isArray(payload)
        ? payload
        : Array.isArray(payload?.data)
          ? payload.data
          : Array.isArray(payload?.data?.rows)
            ? payload.data.rows
            : [];
      level1Tabs.value = normalize(rows);
      // 默认选中接口返回的第一个；若没有数据，则置空
      activeLevel1Id.value = level1Tabs.value.length ? String(level1Tabs.value[0].id) : "";
      // 初始化完成后，同步加载该一级类目的“二/三级树”到搜索项
      await loadSearchCascaderOptions();
    } catch (e) {
      console.error("[GetLevel1CategoryList] error:", e);
      level1Tabs.value = [];
      activeLevel1Id.value = "";
    }
  }

  /** 根据当前一级类目加载 2/3 级树，并注入到搜索项的 cascader */
  async function loadSearchCascaderOptions() {
    if (!activeLevel1Id.value) {
      searchOption.value.formConfig.categoryId.dicData = [];
      return;
    }
    try {
      const res = await Api.service.GetServiceCategoryTree({ id: activeLevel1Id.value });
      // 兜底解析成数组：可能是 res、res.data、res.data.data 其中之一
      const list = Array.isArray(res)
        ? res
        : Array.isArray(res?.data)
          ? res.data
          : Array.isArray(res?.data?.data)
            ? res.data.data
            : [];
      searchOption.value.formConfig.categoryId.dicData = list;
    } catch (e) {
      console.error("[GetServiceCategoryTree] error:", e);
      searchOption.value.formConfig.categoryId.dicData = [];
    }
  }

  /** 切换一级类目：1) 刷新级联选项  2) 清空已选  3) 重新查表 */
  async function handleLevel1Change() {
    // 清空当前搜索的级联选值
    searchParams.value.categoryId = [];
    searchOption.value.formConfig.categoryId.dicData = [];
    await loadSearchCascaderOptions();
    page.currentPage = 1;
    loadGetTableData();
  }

  /* ============== CRUD ============== */
  const crudRef = ref(null);
  function openAddDialog() {
    router.push({ name: "AddContent" });
  }
  function openEditDialog(row) {
    router.push({ name: "UpdateContent", query: { id: row.id } });
  }

  let {
    data: tableData,
    loading: tableLoading,
    page,
    search: searchParams,
    form: formData,
    get: loadGetTableData,
    add: loadAdd,
    edit: loadEdit,
    del: loadDel,
    pageNumChange: loadTablePageChange,
    pageSizeChange: loadTablePageSizeChange,
    searchReset: loadTableSearchReset,
    searchChange: loadTableSearch,
  } = useCrudHook({
    get: Api.service.GetServiceContentPage,
    add: Api.service.AddServiceCategory,
    edit: Api.service.EditServiceContent,
    del: Api.service.DelServiceContent,

    // 若后端为 {code,message,data:{rows,total}} 可开启：
    dataRes: "data.records",
    totalRes: "data.total",

    // 删除确认提示词
    delConfirm: {
      type: "warning",
      title: "删除确认",
      content: "确定要删除该内容吗？删除后用户将不能查看。",
      confirmText: "确定",
      cancelText: "取消",
    },
    search: {},

    getParamsFormat: params => {
      const p = { ...params };

      // 拆分时间区间
      const split = (arr, [s, e]) => {
        if (Array.isArray(arr) && arr.length === 2) {
          p[s] = arr[0];
          p[e] = arr[1];
        }
      };
      split(p.createTime, ["createTimeStart", "createTimeEnd"]);
      delete p.createTime;
      split(p.sendTime, ["sendTimeStart", "sendTimeEnd"]);
      delete p.sendTime;
      split(p.updateTime, ["updateTimeStart", "updateTimeEnd"]);
      delete p.updateTime;

      // 顶部 Tab 的一级类目
      if (activeLevel1Id.value) {
        p.categoryLevel1Id = String(activeLevel1Id.value);
      }

      // 级联选中路径 → 拆成 L2 / L3，同时保留最终叶子为 categoryId
      const path = Array.isArray(p.categoryId) ? p.categoryId.filter(Boolean) : [];
      if (path.length) {
        // 兼容两种形态： [L1, L2, L3] 或 [L2, L3]（以 L1 为根渲染的情况）
        const looksLikeHasL1 = path.length >= 3 || String(path[0]) === String(activeLevel1Id.value);
        const [L1, L2, L3] = looksLikeHasL1 ? [path[0], path[1], path[2]] : [activeLevel1Id.value, path[0], path[1]];

        if (L2) p.categoryLevel2Id = String(L2);
        if (L3) p.categoryLevel3Id = String(L3);

        // 习惯上把“最后一级”也单独传一个字段
        p.categoryId = String(L3 || L2 || L1);
      } else {
        delete p.categoryId; // 没选就不传
      }

      // 清理空值
      Object.keys(p).forEach(k => (p[k] === "" || p[k] == null) && delete p[k]);
      return p;
    },

    addParamsFormat: row => {
      const payload = { ...row };
      if (Array.isArray(payload.categoryId)) {
        payload.categoryId = payload.categoryId[payload.categoryId.length - 1] ?? "";
      }
      if (Number(payload.sendMode) !== 2) payload.planSendTime = "";
      return payload;
    },
    editParamsFormat: row => {
      const payload = { ...row };
      if (Array.isArray(payload.categoryId)) {
        payload.categoryId = payload.categoryId[payload.categoryId.length - 1] ?? "";
      }
      if (Number(payload.sendMode) !== 2) payload.planSendTime = "";
      return payload;
    },
  });

  onMounted(async () => {
    await loadLevel1(); // 先拿一级类目（不加“总 Tab”）
    await loadGetTableData(); // 再查列表
  });
</script>

<style lang="scss" scoped>
  /* 关键1：让左侧 flex 子项能变窄，内部才会出现溢出 */
  .header-left-wrap {
    min-width: 0; /* ★ 必须 */
    flex: 1; /* 如果 header-left/right 需要分配空间 */
  }
  :deep(.x-tabs .el-tabs__nav-scroll) {
    width: calc(80vw);
    // overflow-x: auto;
    overflow-y: hidden;
  }
  :deep(.x-tabs .el-tabs__nav) {
    width: max-content;
    white-space: nowrap;
  }
  :deep(.el-tabs__nav-wrap.is-scrollable) {
    display: flex;
    align-items: center;
  }
  :deep(.el-tabs__nav-prev) {
    margin-top: 5px !important;
  }
  :deep(.el-tabs__nav-next) {
    margin-top: 5px !important;
  }
</style>
